package laf.time;

import java.util.LinkedList;

public class Timer {

	private static Timer instance = new Timer();
	private long tickDuration;
	private long startTime;

	private long currentTick = 0;
	private Thread timer;

	private LinkedList<TimeObserver> observers = new LinkedList<TimeObserver>();

	private Timer() {
		timer = new Thread() {
			public void run() {
				try {
					while (true) {
						wait(tickDuration);
						nextTick();
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
	}

	public static Timer getInstance() {
		return instance;
	}

	public void start(long tickDuration) {
		this.tickDuration = tickDuration;
		startTime = System.currentTimeMillis() / tickDuration;

		timer.start();
	}

	public long getTickDuration() {
		return tickDuration;
	}

	public long waitTime(long ticks) {
		// TODO Return better value
		return ticks * tickDuration;
	}

	public long wakeupTime(long period) {
		return startTime + (currentTime() + period) * tickDuration;
	}

	public long currentTime() {
		return System.currentTimeMillis() / tickDuration - startTime;
	}

	public boolean isStarted() {
		return startTime != 0;
	}

	public void registerObserver(TimeObserver observer) {
		registerObserver(observer, false);
	}

	public void registerObserver(TimeObserver observer, boolean asFirst) {
		if (asFirst) {
			observers.addFirst(observer);
		} else {
			observers.addLast(observer);
		}
	}
	
	private void nextTick() {
		for (TimeObserver observer : observers) {
			observer.tickEnd(currentTick);
		}
		++currentTick;
		for (TimeObserver observer : observers) {
			observer.tickStart(currentTick);
		}
		
	}
}
